/*自身对应的.h文件*/
#include "ui_sysinfo.h"

/*程序内部对应的.h文件*/
#include "log.h"
#include "drv_sys_time.h"

/*外部库对应的.h文件*/
#include "ui.h"

/*系统.h文件*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/***************************************************************
 * Name:	 get_cmd_ret()
 * Input : cmd运行的命令
 * Output: ret_buf存储返回的缓存区 ret_buf_size缓存区大小
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 运行命令并获取返回值
 ***************************************************************/
static int get_cmd_ret(const char *cmd, char* ret_buf, size_t ret_buf_size)
{
	FILE *fp = popen(cmd, "r");
	if(fp == NULL)
	{
		printf("Failed to run command\n");
		return -1;
	}

	size_t all_read_len = 0;

	static char buf[100];
	memset(buf, 0x00, sizeof(buf));
	/*缓存区还有空闲并且 还没读取完*/
	while (all_read_len < ret_buf_size && fgets(buf, sizeof(buf), fp) != NULL)
	{
		/*获取读取到的长度*/
		size_t cur_read_len = strlen(buf);
		/*保存数据*/
		if(cur_read_len + all_read_len > ret_buf_size)
		{
			cur_read_len = ret_buf_size - all_read_len;
		}
		memcpy(ret_buf + all_read_len, buf, cur_read_len);
		/*更新读取到的长度*/
		all_read_len += cur_read_len;
	}

	pclose(fp);

	return 0;
}

/***************************************************************
 * Name:	 update_cur_time_info()
 * Input : void
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 更新当前时间信息显示
 ***************************************************************/
static int update_cur_time_info(void)
{
	// 定义一个time_t类型的变量来存储时间
	time_t current_time;
	// 获取当前时间
	time(&current_time);
	// 将time_t类型的当前时间转换为本地时间
	struct tm *local_time = localtime(&current_time);
	
	lv_label_set_text_fmt(ui_SysInfoLabDate, "%d-%02d-%02d %02d:%02d:%02d",
					local_time->tm_year + 1900,	// tm_year是从1900年开始的，所以需要加1900
					local_time->tm_mon + 1,			// tm_mon是从0开始的，所以需要加1
					local_time->tm_mday,
					local_time->tm_hour,
					local_time->tm_min,
					local_time->tm_sec);
}

/***************************************************************
 * Name:	 update_run_time_info()
 * Input : void
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 更新运行时间信息显示
 ***************************************************************/
static int update_run_time_info(void)
{
	lv_label_set_text_fmt(ui_SysInfoLabRunTime, "%ldS", drv_sys_time_get_time_ms() / 1000);
}

/***************************************************************
 * Name:	 get_cpu_info()
 * Input : buf_size存储空间大小
 * Output: buf存储空间
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 获取CPU信息
 ***************************************************************/
static int get_cpu_info(char* buf, size_t buf_size)
{
	static char mid_buf[100], end_buf[100];

	memset(mid_buf, 0x00, sizeof(mid_buf));
	memset(end_buf, 0x00, sizeof(end_buf));

	if(get_cmd_ret(" lscpu | grep -i \"Model name:\" | cut -d':' -f 2", mid_buf, sizeof(mid_buf)) != 0)
	{
		LOG_WARNING("cmd run fail\r\n");
		return -1;
	}

	sscanf(mid_buf, "%s\n", end_buf);

	memset(buf, 0x00, buf_size);
	strncpy(buf, end_buf, strlen(end_buf) > buf_size ? buf_size : strlen(end_buf));

	return 0;
}

/***************************************************************
 * Name:	 update_cpu_info()
 * Input : void
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 更新CPU信息显示
 ***************************************************************/
static int update_cpu_info(void)
{
	char buf[100];
	if(get_cpu_info(buf, sizeof(buf)) == 0)
	{
		lv_label_set_text_fmt(ui_SysInfoLabCPUName, "%s", buf);
		return 0;
	}
	else
	{
		return -1;
	}
}

/***************************************************************
 * Name:	 get_ram_info()
 * Input : void
 * Output: all所有的存储空间 free空闲的存储空间
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 获取设备内存信息
 ***************************************************************/
static int get_ram_info(float *all, float *free)
{
	static char buf[1024] = {0};

	memset(buf, 0x00, sizeof(buf));

	if(get_cmd_ret("cat /proc/meminfo", buf, sizeof(buf)) != 0)
	{
		LOG_WARNING("cmd run fail\r\n");
		return -1;
	}

	char *res = strstr(buf, "MemTotal:");
	if(res != NULL)
	{
		unsigned long data = 0;
		sscanf(res, "MemTotal: %lu kB\n", &data);
		*all = (float)data / 1024.0f /1024.0f;
	}
	else
	{
		LOG_WARNING("get MemTotal failed\r\n");
		return -1;
	}

	res = strstr(buf, "MemAvailable:");
	if(res != NULL)
	{
		unsigned long data = 0;
		sscanf(res, "MemAvailable: %lu kB\n", &data);
		*free = (float)data / 1024.0f /1024.0f;
	}
	else
	{
		LOG_WARNING("get MemAvailable failed\r\n");
		return -1;
	}

	return 0;
}

/***************************************************************
 * Name:	 update_ram_info()
 * Input : void
 * Output: all所有的存储空间 free空闲的存储空间
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 更新设备内存信息显示
 ***************************************************************/
static int update_ram_info(void)
{
	float all_mem = 0, free_mem = 0;
	if(get_ram_info(&all_mem, &free_mem) == 0)
	{
		lv_label_set_text_fmt(ui_SysInfoLabRAMSize, "%.2fGb / %.2fGb", free_mem, all_mem);
		return 0;
	}
	else
	{
		return -1;
	}
}

/***************************************************************
 * Name:	 get_flash_info()
 * Input : void
 * Output: all所有的存储空间 free空闲的存储空间
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 获取设备硬盘信息
 ***************************************************************/
static int get_flash_info(float *all, float *free)
{
	static char buf[1024] = {0};

	memset(buf, 0x00, sizeof(buf));

	if(get_cmd_ret("df -h", buf, sizeof(buf)) != 0)
	{
		LOG_WARNING("cmd run fail\r\n");
		return -1;
	}
	
	char *res = strstr(buf, "/dev/mmcblk0p3");
	if(res != NULL)
	{
		float data1 = 0, data2 = 0, data3 = 0;
		sscanf(res, "/dev/mmcblk0p3 %fG %fG %fG \n", &data1, &data2, &data3);
		*all = data1;
		*free = data3;
	}
	else
	{
		LOG_WARNING("get /dev/mmcblk0p3 failed\r\n");
		return -1;
	}

	return 0;
}

/***************************************************************
 * Name:	 update_flash_info()
 * Input : void
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 更新设备硬盘信息显示
 ***************************************************************/
static int update_flash_info(void)
{
	float all = 0, free = 0;
	if(get_flash_info(&all, &free) == 0)
	{
		lv_label_set_text_fmt(ui_SysInfoLabFLASHSize, "%.1fGb / %.1fGb", free, all);
	}
	else
	{
		return -1;
	}
}

/***************************************************************
 * Name:	 get_temp_info()
 * Input : void
 * Output: temp核心的温度
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 获取设备温度信息
 ***************************************************************/
static int get_temp_info(float *temp)
{
	static char buf[10] = {0};

	memset(buf, 0x00, sizeof(buf));

	if(get_cmd_ret("cat /sys/class/thermal/thermal_zone0/temp", buf, sizeof(buf)) != 0)
	{
		LOG_WARNING("cmd run fail\r\n");
		return -1;
	}

	uint16_t data = 0;
	sscanf(buf, "%hd \n", &data);

	*temp = (float)data / 1000.0f;
	
	return 0;
}

/***************************************************************
 * Name:	 update_temp_info()
 * Input : void
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 更新设备温度信息显示
 ***************************************************************/
static int update_temp_info(void)
{
	float temp = 0;
	if(get_temp_info(&temp) == 0)
	{
		lv_label_set_text_fmt(ui_SysInfoLabCPUTemp, "%.2fC", temp);
		return -1;
	}
	else
	{
		return 0;
	}
}

/***************************************************************
 * Name:	 update_cpufan_info()
 * Input : void
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 更新设备风扇信息显示
 ***************************************************************/
static int update_cpufan_info(void)
{
	ui_event_param_t param = {
		.obj = ui_SysInfoBtnCPUFanMode,
		.obj_name = SYSINFO_BTN_CPUFAN_CLICK_CB,
	};
	ui_sysinfo_event_cb(param);
}

/***************************************************************
 * Name:	 ui_sysinfo_init()
 * Input : void
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 系统信息界面初始化
 ***************************************************************/
int ui_sysinfo_init(void)
{
	/*软件信息*/
	{
		/*软件版本号*/
		lv_label_set_text_fmt(ui_SysInfoLabVersion, "%s-%s", __DATE__, __TIME__);

		/*编译时间*/
		lv_label_set_text_fmt(ui_SysInfoLabBuildTime, "%s %s", __DATE__, __TIME__);

		/*当前时间*/
		update_cur_time_info();

		/*运行时间*/
		update_run_time_info();
	}

	/*硬件信息*/
	{
		/*CPU型号*/
		update_cpu_info();

		/*内存*/
		update_ram_info();

		/*硬盘*/
		update_flash_info();

		/*温度*/
		update_temp_info();

		/*CPU风扇*/
		update_cpufan_info();
	}

	return 0;
}

/***************************************************************
 * Name:	 ui_sys_info_poll()
 * Input : void
 * Output: void
 * Return: void
 * Author: hwl
 * Revise: V1.0
 * Description: 系统信息界面更新
 ***************************************************************/
void ui_sysinfo_update(void)
{
	static uint64_t last_update_t = 0;

	if(drv_sys_time_pase_time_ms(last_update_t) > 1 * 1000)
	{
		last_update_t = drv_sys_time_get_time_ms();
		/*软件信息*/
		{
			/*当前时间*/
			update_cur_time_info();

			/*运行时间*/
			update_run_time_info();
		}

		/*硬件信息*/
		{
			/*内存*/
			update_ram_info();

			/*硬盘*/
			update_flash_info();

			/*温度*/
			update_temp_info();
		}
	}
}

/***************************************************************
 * Name:	 btn_cpufan_click_cb()
 * Input : param事件参数
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: CPU风扇工作模式设置回调函数
 ***************************************************************/
static int btn_cpufan_click_cb(ui_event_param_t param)
{
	if(lv_obj_has_state(param.obj, LV_STATE_CHECKED) == false)
	{
		lv_label_set_text_fmt(ui_SysInfoLabCPUFanMode, "%s", "AUTO");
	}
	else
	{
		lv_label_set_text_fmt(ui_SysInfoLabCPUFanMode, "%s", "HAND");
	}
	return 0;
}


/***************************************************************
 * Name:	 cpufan_speed_change()
 * Input : param事件参数
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: CPU风扇回调转速函数
 ***************************************************************/
static int drop_cpufan_change_cb(ui_event_param_t param)
{
	char str[20] = "";
	lv_dropdown_get_selected_str(param.obj, str, 20);

	LOG_DEBUG("%s\r\n", str);

	return 0;
}

/***************************************************************
 * Name:	 btn_back_click_cb()
 * Input : param事件参数
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 返回按键点击回调函数
 ***************************************************************/
static int btn_back_click_cb(ui_event_param_t param)
{
	lv_scr_load(ui_Main);

	return 0;
}

/*UI事件回调列表*/
static ui_event_cb_list_t g_event_cb_list[] = {
	[0] = {
		.obj_name = SYSINFO_BTN_CPUFAN_CLICK_CB,
		.obj_cb = btn_cpufan_click_cb,
	},
	[1] = {
		.obj_name = SYSINFO_DROP_CPUFAN_CHANGE_CB,
		.obj_cb = drop_cpufan_change_cb,
	},
	[2] = {
		.obj_name = SYSINFO_BTN_BACK_CLICK_CB,
		.obj_cb = btn_back_click_cb,
	},
};

/***************************************************************
 * Name:	 ui_sysinfo_event_cb()
 * Input : param 事件参数
 * Output: void
 * Return: 0成功 <0失败
 * Author: hwl
 * Revise: V1.0
 * Description: 系统信息界面事件回调函数
 ***************************************************************/
int ui_sysinfo_event_cb(ui_event_param_t param)
{
	for(uint8_t i = 0; i < sizeof(g_event_cb_list) / sizeof(ui_event_cb_list_t); i++)
	{
		if(strcmp(g_event_cb_list[i].obj_name, param.obj_name) == 0)
		{
			return g_event_cb_list[i].obj_cb(param);
		}
	}

	return -1;
}